﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using BalancaClient.ServicoIntrep;
using System.ServiceModel;
using System.Net;

namespace BalancaClient
{
    public partial class frmCliente : Form
    {
        private Object thislock = new Object();
        delegate void SetTextCallback(string text);

        private volatile bool comunicate;

        private Thread ThreadComunicar { get; set; }
        private TcpClient Server { get; set; }

        private NetworkStream ServerStream { get; set; }

        private IntrepServiceClient clientews { get; set; }
        private bool wcfativo = false;

        public frmCliente()
        {
            InitializeComponent();

            Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - this.Width -10, 10);

            Thread.CurrentThread.Name = "ServerForm";
        }

        private void frmCliente_Load(object sender, EventArgs e)
        {
            Log("Cliente iniciado");
            btnConectar.PerformClick();           

            VerificaWebService();
        }

        public void Start()
        {
            comunicate = true;

            AlternaBotoes();
        }

        public void Stop()
        {
            comunicate = false;

            Server.Close();
            AlternaBotoes();
        }

        private void btnConectar_Click(object sender, EventArgs e)
        {
            Server = new TcpClient();

            Start();

            try
            {
                Server.Connect(txtEndereco.Text, Convert.ToInt16(txtPorta.Text));

                ThreadComunicar = new Thread(new ParameterizedThreadStart(Comunicar));
                ThreadComunicar.Name = "Cliente " + ThreadComunicar.ManagedThreadId;
                ThreadComunicar.Start(Server);

                Log("Conectado a " + Server.Client.RemoteEndPoint.ToString());

                //AlternaBotoes();
            }
            catch (Exception ex)
            {
                Log("Não foi possível conectar");
                debugmsg("ERRO: " + ex.Message);
                AlternaBotoes();
            }
        }
        private void btnDesconectar_Click(object sender, EventArgs e)
        {
            btnDesconectar.Enabled = false;
            Stop();

            Log("Desconectado");            
        }

        private void AlternaBotoes()
        {
            MethodInvoker action = delegate
            {
                btnConectar.Enabled = btnDesconectar.Enabled;
                btnDesconectar.Enabled = !btnConectar.Enabled;

                txtEndereco.Enabled = txtPorta.Enabled = btnConectar.Enabled;
            };

            try
            {
                lock (thislock)
                {
                    Invoke(action);
                }
            }
            catch (ObjectDisposedException)
            {
                Thread.CurrentThread.Interrupt();
            }
            
        }

        public void Comunicar(object server)
        {
            ASCIIEncoding encoder = new ASCIIEncoding();

            Server = (TcpClient)server;
            ServerStream = Server.GetStream();

            byte[] message = new byte[4096];

            int bytesLidos;
            int falhas = 0;

            byte[] resposta = null;

            Log("Início da comunicação");
            while (comunicate)
            {
                if (falhas >= 4)
                {
                    Log("Servidor desconectou");
                    Stop();
                    break;
                }

                bytesLidos = 0;

                if (chkRespostaCorreta.Checked)
                    resposta = encoder.GetBytes('\x02' + "82SP|" + '\x03');
                else
                    resposta = encoder.GetBytes("bla");

                //ServerStream.Write(resposta, 0, resposta.Length);
                Server.Client.Send(resposta);

                try
                {
                    bytesLidos = ServerStream.Read(message, 0, 4096);
                    if (bytesLidos > 1)
                    {
                        string msg = encoder.GetString(message, 0, bytesLidos);
                        Log(msg);
                        if (wcfativo)
                        {
                            try
                            {
                                clientews.recebeString(msg);
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }
                        }
                    }
                    else if (bytesLidos == 0)
                    {
                        falhas++;
                    }

                }
                catch (IOException e)
                {
                    debugmsg("IO: " + e.Message);
                    comunicate = false;
                    break;
                }
                catch (Exception e)
                {
                    debugmsg("ERRO: " + e.Message);
                    comunicate = false;
                    break;
                }
                Thread.Sleep(1000);
            }
            Log("Fim da comunicação");
            ServerStream.Close();

            Stop();
        }

        public void Log(string msg)
        {
            if (msg.Length > 1)
            {
                if (txtClientStatus.InvokeRequired)
                {
                    SetTextCallback d = new SetTextCallback(Log);
                    Invoke(d, new object[] { msg });
                }
                else
                {
                    txtClientStatus.Text += DateTime.Now.ToLongTimeString() + " -> " + msg;
                    txtClientStatus.Text += Environment.NewLine;
                    lblClientStatus.Text = msg;

                    txtClientStatus.SelectionStart = txtClientStatus.Text.Length;
                    txtClientStatus.ScrollToCaret();
                } 
            }
        }

        private void debugmsg(string p)
        {
            System.Diagnostics.Debug.WriteLine("Cliente " + DateTime.Now.ToLongTimeString() + " -> " + p);
        }

        private void btnVerificarWS_Click(object sender, EventArgs e)
        {
            VerificaWebService();
        }

        private void VerificaWebService()
        {
            btnVerificarWS.Text = "Verificando";
            btnVerificarWS.Enabled = false;

            BasicHttpBinding binding = new BasicHttpBinding();
            EndpointAddress endpoint = new EndpointAddress(new Uri(txtWebServiceUrl.Text));

            clientews = new IntrepServiceClient(binding, endpoint);

            WebRequest request = WebRequest.Create(txtWebServiceUrl.Text);
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                if (response == null || response.StatusCode != HttpStatusCode.OK)
                    Log("Web Service Indisponível");
                else
                {
                    Log("Web Service OK");
                    wcfativo = true;
                }

                response.Close();
            }
            catch (WebException ex)
            {
                Log("Web Service Indisponível");
            }
            finally
            {
                btnVerificarWS.Text = "Verificar";
                btnVerificarWS.Enabled = true;
            }
        }
    }
}
